package com.telnetnz.ticketdesk.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sf.ehcache.Element;

import org.apache.log4j.Logger;

import com.rockbb.common.simpleframe.config.SimpleConfig;
import com.rockbb.common.simpleframe.result.ActionResult;
import com.rockbb.common.utilities.i18n.MessageResource;
import com.rockbb.common.utilities.i18n.MessageResourceFactory;
import com.telnetnz.ticketdesk.bean.ProjectToUser;
import com.telnetnz.ticketdesk.bean.Template;
import com.telnetnz.ticketdesk.bean.Ticket;
import com.telnetnz.ticketdesk.common.GenericPageMaker;
import com.telnetnz.ticketdesk.common.config.SpringContext;
import com.telnetnz.ticketdesk.dao.entity.TicketEntity;
import com.telnetnz.ticketdesk.dao.wrapper.TicketWrap;

public class TicketService
{
	public static final String[] ORDER_BY = TicketWrap.ORDER_BY;
	public static final int ORDERBY_ID = 0;
	public static final int ORDERBY_PRIORITY = 1;
	public static final int ORDERBY_DUEDATE = 2;
	public static final int ORDERBY_CREATETIME = 3;
	public static final int ORDERBY_UPDATETIME = 4;
	public static final int ORDERBY_STATUS = 5;

	public static final String[] ORDER = TicketWrap.ORDER;

	public static final String[] TYPES = TicketWrap.TYPES;
	public static final String[] PRIORITIES = TicketWrap.PRIORITIES;

	public static final String[] STATUSES = TicketWrap.STATUSES;
	public static final int STATUS_NEW = 0;
	public static final int STATUS_PROGRESS = 1;
	public static final int STATUS_CLOSED = 2;
	public static final int STATUS_CANCELED = 3;

	private static Logger logger = Logger.getLogger(TicketService.class);
	private static String CACHE_KEY = "id_";

	public static void sendUpdateNotification(Ticket ticket, int language)
	{
		Set<String> recipients = new HashSet<String>();
		recipients.add(ticket.getCreator().getEmail());
		if (ticket.getOwner() == null)
		{
			List<ProjectToUser> users = ticket.getProject().getProjectUsers();
			for (ProjectToUser user: users)
				recipients.add(user.getUser().getEmail());
		}
		else
			recipients.add(ticket.getOwner().getEmail());

		Map<String, Object> root = new HashMap<String, Object>();
		MessageResource langRes = MessageResourceFactory.getMessageResource(language);

		root.put("ticket", ticket);
		root.put(ActionResult.MAP_KEY_I18N, langRes.getResourceBundle());	// L("") = i18n method
		root.put(ActionResult.MAP_KEY_CONFIGS, SimpleConfig.getConfigs());	// sf_configs = Global configurations

		Template template = TemplateService.getTemplate(1);
		StringBuffer sb = new StringBuffer()
				.append('[').append(ticket.getProject().getName()).append("][")
				.append(TicketService.PRIORITIES[ticket.getPriority()]).append("][")
				.append(TicketService.STATUSES[ticket.getStatus()]).append("] ")
				.append(ticket.getSubject());
		String subject = sb.toString();

		String formattedContent = GenericPageMaker.process(template.getName(), SimpleConfig.getConfig("encoding"), root);

		SMTPService.sendMail(
				subject, 
				formattedContent, 
				SimpleConfig.getConfig("encoding"),
				recipients);
	}

	public static void updateBatchToProjectId(int sourceProjectId, int targetProjectId)
	{
		getWrap().updateBatchToProjectId(sourceProjectId,  targetProjectId);
		getWrap().getCache().removeAll();
	}

	/**
	 * Important: This is only for comparison with the updated bean
	 * 
	 * @param uid
	 * @return
	 */
	public static Ticket getRawTicket(long id)
	{
		TicketEntity entity = getWrap().select(id);
		return Ticket.adapt(entity);
	}

	/**
	 * Important: This is the only entry to get the ticket bean, including the methods that return instances list
	 * 
	 * @param uid
	 * @return
	 */
	public static Ticket getTicket(long id)
	{
		Element elm = getWrap().getCache().get(CACHE_KEY + id);
		Ticket bean;
		if (elm == null)
		{
			TicketEntity entity = getWrap().select(id);
			bean = Ticket.adapt(entity);
			getWrap().getCache().put(new Element(CACHE_KEY + id, bean));
		}
		else
		{
			bean = (Ticket) elm.getValue();
		}
		return bean;
	}

	public static void add(Ticket ticket)
	{
		if (ticket == null)
			return;
		getWrap().insert(ticket.toEntity());
		getWrap().getCache().remove(CACHE_KEY + ticket.getId());

		TicketToUserService.add(ticket.getId(), ticket.getCreatorId());
	}

	public static void update(Ticket ticket)
	{
		if (ticket == null)
			return;
		ticket.setUpdateTime(new Date());
		getWrap().update(ticket.toEntity());
		getWrap().getCache().remove(CACHE_KEY + ticket.getId());

		TicketToUserService.add(ticket.getId(), ticket.getOwnerId());
	}

	public static void delete(Ticket ticket)
	{
		if (ticket == null)
			return;
		getWrap().delete(ticket.toEntity());
		getWrap().getCache().remove(CACHE_KEY + ticket.getId());
	}

	public static List<Ticket> getByPageAndCondition(
			int start,
			int limit, 
			int orderby, 
			int order,
			List<Integer>  projectIds,
			long extraCreatorId,
			long memberId,
			List<Long> ownerIds,
			long creatorId,
			long updaterId,
			String subject,
			String content,
			int priority,
			int type,
			List<Integer> statuses,
			List<Integer> excludedStatuses,
			long tagId,
			Date dueAfter,
			Date dueBefore,
			Date createAfter,
			Date createBefore,
			Date updateAfter,
			Date updateBefore)
	{
		List<Long> ids = getWrap().selectByPageAndCondition(
				start, 
				limit, 
				orderby, 
				order, 
				projectIds, 
				extraCreatorId, 
				memberId, 
				ownerIds, 
				creatorId, 
				updaterId, 
				subject, 
				content, 
				priority, 
				type, 
				statuses, 
				excludedStatuses, 
				tagId, 
				dueAfter, 
				dueBefore, 
				createAfter, 
				createBefore, 
				updateAfter, 
				updateBefore);
		return adaptIdsList(ids);
	}

	public static long countByCondition(
			List<Integer>  projectIds,
			long extraCreatorId,
			long memberId,
			List<Long> ownerIds,
			long creatorId,
			long updaterId,
			String subject,
			String content,
			int priority,
			int type,
			List<Integer> statuses,
			List<Integer> excludedStatuses,
			long tagId,
			Date dueAfter,
			Date dueBefore,
			Date createAfter,
			Date createBefore,
			Date updateAfter,
			Date updateBefore)
	{
		return getWrap().countByCondition(
				projectIds, 
				extraCreatorId, 
				memberId, 
				ownerIds, 
				creatorId, 
				updaterId, 
				subject, 
				content, 
				priority, 
				type, 
				statuses, 
				excludedStatuses, 
				tagId, 
				dueAfter, 
				dueBefore, 
				createAfter, 
				createBefore, 
				updateAfter, 
				updateBefore);
	}

	private static List<Ticket> adaptIdsList(List<Long> ids)
	{
		List<Ticket> tickets = new ArrayList<Ticket>();
		if (ids != null && ids.size() > 0)
		{
			for (Long id : ids)
			{
				Ticket ticket = getTicket(id);
				if (ticket != null)
					tickets.add(ticket);
			}
		}
		return tickets;
	}

	private static TicketWrap getWrap()
	{
		return SpringContext.getTicketWrap();
	}

	public static void main(String[] args)
	{
		Ticket ticket = TicketService.getRawTicket(18);
		sendUpdateNotification(ticket, 1);
	}
}
